Loading an XML document
XML is part of the acronym
AJAX, but we haven't actually loaded any XML yet. Doing so is
straightforward, and mirrors the JSON technique fairly closely. First
we'll need an XML file d.xml containing some data we wish to display:
<?xml version="1.0" encoding="UTF-8"?>
<entries>
<entry term="DEFAME" part="v.t.">
<definition>
To lie about another. To tell the truth about another.
</definition>
</entry>
<entry term="DEFENCELESS" part="adj.">
<definition>
Unable to attack.
</definition>
</entry>
<entry term="DELUSION" part="n.">
<definition>
The father of a most respectable family, comprising
Enthusiasm, Affection, Self-denial, Faith, Hope,
Charity and many other goodly sons and daughters.
</definition>
<quote author="Mumfrey Mappel">
<line>All hail, Delusion! Were it not for thee</line>
<line>The world turned topsy-turvy we should see;
</line>
<line>For Vice, respectable with cleanly fancies,
</line>
<line>Would fly abandoned Virtue's gross advances.
</line>
</quote>
</entry>
<entry term="DIE" part="n.">
<definition>
The singular of "dice." We seldom hear the word,
because there is a prohibitory proverb, "Never say
die." At long intervals, however, some one says: "The
die is cast," which is not true, for it is cut. The
word is found in an immortal couplet by that eminent
poet and domestic economist, Senator Depew:
</definition>
<quote>
<line>A cube of cheese no larger than a die</line>
<line>May bait the trap to catch a nibbling mie.</line>
</quote>
</entry>
</entries>
This data could be
expressed in many ways, of course, and some would more closely mimic the
structure we established for the HTML or JSON used earlier. Here,
however, we're illustrating some of the features of XML designed to make
it more readable to humans, such as the use of attributes for term and part rather than tags.
We'll start off our function in a familiar manner:
$(document).ready(function() {
$('#letter-d a').click(function() {
$.get('d.xml', function(data) {
});
return false;
});
});
This time it's the $.get()
function that does our work. In general, this function simply fetches
the file at the supplied URL and provides the plain text to the
callback. However, if the response is known to be XML because of its
server-supplied MIME type, the callback will be handed the XML DOM tree.
Fortunately, as we have already seen, jQuery has substantial DOM traversing capabilities. We can use the normal .find(), .filter() and other traversal methods on the XML document just as we would on HTML:
$(document).ready(function() {
$('#letter-d a').click(function() {
$.get('d.xml', function(data) {
$('#dictionary').empty();
$(data).find('entry').each(function() {
var $entry = $(this);
var html = '<div class="entry">';
html += '<h3 class="term">' + $entry.attr('term')
+ '</h3>';
html += '<div class="part">' + $entry.attr('part')
+ '</div>';
html += '<div class="definition">';
html += $entry.find('definition').text();
var $quote = $entry.find('quote');
if ($quote.length) {
html += '<div class="quote">';
$quote.find('line').each(function() {
html += '<div class="quote-line">'
+ $(this).text() + '</div>';
});
if ($quote.attr('author')) {
html += '<div class="quote-author">'
+ $quote.attr('author') + '</div>';
}
html += '</div>';
}
html += '</div>';
html += '</div>';
$('#dictionary').append($(html));
});
});
return false;
});
});
This has the expected effect when the D link is clicked:
This is a new use for
the DOM traversal methods we already know, shedding some light on the
flexibility of jQuery's CSS selector support. CSS syntax is typically
used to help beautify HTML pages, and thus selectors in standard .css files use HTML tag names such as div and body to locate content. However, jQuery can use arbitrary XML tag names, such as entry and definition here, just as readily as the standard HTML ones.
The advanced selector engine inside jQuery facilitates finding parts of
the XML document in much more complicated situations, as well. For
example, suppose we wanted to limit the displayed entries to those that
have quotes that in turn have attributed authors. To do this, we can
limit the entries to those with nested<quote> elements by changing entry to entry:has(quote). Then we can further restrict the entries to those with author attributes on the<quote> elements by writing entry:has(quote[author]). The line with the initial selector now reads:
$(data).find('entry:has(quote[author])').each(function() {
This new selector expression restricts the returned entries correspondingly: